package iso3.pt.dao;



import iso3.pt.model.Alumno;
import iso3.pt.model.Asignatura;
import iso3.pt.model.Evaluacion;
import iso3.pt.model.Profesor;
import iso3.pt.model.Unidad;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class PtDAO implements PtDAOInterface
{
	SessionFactory sessionFactory;
	private static PtDAO instance = null;
	private static Session session;
	private static Map<Integer,Asignatura> asignaturas;

	private PtDAO()
	{
		sessionFactory = new Configuration().configure().buildSessionFactory();
		session = sessionFactory.openSession();
		List lAsignaturas = (session.createQuery("from Asignatura ")).list();
		PtDAO.asignaturas = new HashMap<Integer,Asignatura>();
		for (int i = 0; i < lAsignaturas.size(); i++)
		{
			PtDAO.asignaturas.put(((Asignatura)lAsignaturas.get(i)).getId(), (Asignatura)lAsignaturas.get(i));
		}
	}
	
	public void close()
	{
		session.close();
	}

	public static PtDAO getInstance()
	{
		if (instance == null)
		{
			instance = new PtDAO();
		}
		return instance;
	}

	@Override
	public Profesor getProfesor(int idAsignatura)
	{
		return (PtDAO.asignaturas.get(idAsignatura)).getProfesor();
	}

	@Override
	public Set<Alumno> getAlumnos(int idAsignatura)
	{
		return (PtDAO.asignaturas.get(idAsignatura)).getAlumnos();
	}

	@Override
	public List<Evaluacion> getEvaluacionesOrderedByAsignatura(int idAlumno)
	{
		List<Evaluacion> evaluaciones = new ArrayList<Evaluacion>();
		List<Asignatura> lista = new ArrayList<Asignatura>(asignaturas.values());
		
		for (int i=0; i<lista.size(); i++)
			evaluaciones.addAll((HashSet<? extends Evaluacion>) getEvaluaciones(lista.get(i).getId(), idAlumno));
		
		return evaluaciones;
	}

	@Override
	public Set<Evaluacion> getEvaluaciones(int idAsignatura, int idAlumno)
	{	
		Set<Evaluacion> evaluaciones= new HashSet<Evaluacion>();;
		
		List<Evaluacion> x = getEvaluacionesAsignatura(idAsignatura);
		
		for (int i=0; i < x.size(); i++)
			if (x.get(i).getAlumno().getDni().equals(idAlumno))
				evaluaciones.add(x.get(i));
		
		return evaluaciones;
	}

	@Override
	public void addEvaluacion(String concepto, float nota, int idAsignatura, int idAlumno)
	{
		Transaction tx = session.beginTransaction();
		Evaluacion ev = new Evaluacion(concepto, nota);
		ev.setAsignatura(getAsignatura(idAsignatura));
		Alumno al = getAlumno(idAlumno);
		al.addEvaluacion(ev);
		ev.setAlumno(al);
		session.save(ev);
		tx.commit();
	}

	@Override
	public Set<Unidad> getUnidades(int idAsignatura)
	{
		return (PtDAO.asignaturas.get(idAsignatura)).getUnidades();
	}

	@Override
	public Set<Asignatura> getAsignaturas()
	{ 
		List<Asignatura> lista = new ArrayList<Asignatura>(asignaturas.values());
		return new HashSet<Asignatura> (lista);
	}

	@Override
	public Alumno getAlumno(int id)
	{	
		return (Alumno)session.get(Alumno.class, id);
	}

	@Override
	public Asignatura getAsignatura(int id)
	{
		return PtDAO.asignaturas.get(id);
	}

	@Override
	public Alumno loginAlumno(int dni, String pass) throws UserNotFoundException, IncorrectPasswordException
	{
		if (getAlumno(dni)== null)
		{
			throw new UserNotFoundException(dni);
		}
		
		else if(!getAlumno(dni).getPassword().equals(pass))
		{
			throw new IncorrectPasswordException();
		}
		
		else return getAlumno(dni);
	}

	@Override
	public Set<Asignatura> getAsignaturas(int idAlumno)
	{
		return getAlumno(idAlumno).getAsignaturas();	
	}

	@Override
	public void matricular(int idAlumno, int idAsignatura)
	{
		Transaction tx = session.beginTransaction();
		Asignatura as = PtDAO.asignaturas.get(idAsignatura);
		Alumno al = getAlumno(idAlumno);
		al.addAsignatura(as);
		as.addAlumno(al);
		session.save(as);
		session.save(al);
		tx.commit();
	}

	@Override
	public void desmatricular(int idAlumno, int idAsignatura)
	{
		Transaction tx = session.beginTransaction();
		Asignatura as = PtDAO.asignaturas.get(idAsignatura);
		Alumno al = getAlumno(idAlumno);		
		al.removeAsignatura(as);
		as.removeAlumno(al);
		session.save(as);
		session.save(al);
		tx.commit();
		
	}

	@Override
	public Profesor loginProfesor(int dni, String pass) throws UserNotFoundException, IncorrectPasswordException
	{
		if (getProfesorByDni(dni)== null)
		{
			throw new UserNotFoundException(dni);
		}
		
		else if(!getProfesorByDni(dni).getPassword().equals(pass))
		{
			throw new IncorrectPasswordException();
		}
		
		else return getProfesorByDni(dni);
	}

	@Override
	public Set<Asignatura> getAsignaturasProfesor(int idProfesor)
	{
		Set<Asignatura> x = new HashSet<Asignatura>();		
		List<Asignatura> lista = new ArrayList<Asignatura>(asignaturas.values());
		for (int i=0; i < lista.size(); i++)
			if (lista.get(i).getProfesor().getId() == idProfesor)
				x.add(lista.get(i));
		
		return x;
	}

	@Override
	public Profesor getProfesorByDni(int dni) throws UserNotFoundException
	{		
		List<Asignatura> lista = new ArrayList<Asignatura>(asignaturas.values());
		for (int i=0; i <lista.size();i++)
		{	
			Profesor prof = lista.get(i).getProfesor();
			if (prof.getDni() == dni)
				return prof;
		}
		
		throw new UserNotFoundException(dni);
	}

	@Override
	public List<Evaluacion> getEvaluacionesAsignatura(int idAsignatura)
	{		
		return (session.createQuery("from Evaluacion where AS_ID = "+ Integer.toString(idAsignatura)).list());	
	}
} 
